# add -DDEBUG_MEM to turn on memory allocation logging
-CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync
+CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync
INSTALL_TARGETDIR=/usr/local/
FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \
psp.o holux.o garmin.o tmpro.o tpg.o \
xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o gpilots.o
-FILTERS=position.o duplicate.o arcdist.o
+FILTERS=position.o duplicate.o arcdist.o polygon.o
JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \
jeeps/gpsmath.o jeeps/gpsmem.o \
COLDSYNC=coldsync/util.o coldsync/pdb.o
-OBJS=main.o queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o csv_util.o \
+LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o csv_util.o \
$(COLDSYNC) $(GARMIN) $(JEEPS) $(FMTS) $(FILTERS)
+OBJS = main.o $(LIBOBJS)
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
# Machine generated from here down.
+arcdist.o: arcdist.c defs.h queue.h
cetus.o: cetus.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
quovadis.o: quovadis.c defs.h queue.h coldsync/palm.h coldsync/pdb.h quovadis.h
copilot.o: copilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
gpx.o: gpx.c defs.h queue.h
holux.o: holux.c defs.h queue.h holux.h
internal_styles.o: internal_styles.c defs.h queue.h
+polygon.o: polygon.c defs.h queue.h
magnav.o: magnav.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
magproto.o: magproto.c defs.h queue.h magellan.h
main.o: main.c defs.h queue.h
locations. The result would be a GPX file that more than likely
contains only unique points and point data.
- DISTANCE ALONG A ROUTE
+ DISTANCE ALONG A ROUTE (ARC)
The arc filter is designed to include points based on their
proximity to an arc, which is a series of connected line
that distance is declared on the command line with the
distance=X.XX option to the filter. Distance options may be
expressed in miles (distance=3M) or kilometers (distance=3K).
- The default is zero miles.
+ The default is zero miles. You may also specify the exclude option,
+ which causes GPSBabel to only include points that are further than
+ the specified distance from the arc.
For example, assuming the arc above is in a file called "lima_rd.txt":
would include only points within one mile of the section of Lima Road
covered by the arc.
+ POLYGON
+
+ The polygon filter includes points if they are inside of a polygon.
+ A polygon file looks like an arc file, except that the arc it
+ describes must be a closed cycle. That is, for a simple polygon,
+ the first and last points must be the same. Here's a square:
+
+ # A square (not really) polygon
+ 41.0000 -85.0000
+ 41.0000 -86.0000
+ 42.0000 -86.0000
+ 42.0000 -85.0000
+ 41.0000 -85.0000
+
+ Polygons may include islands and holes. To specify an island or a
+ hole, just append it to the main polygon.
+
+ As with the arc filter, you specify a polygon by specifying the name
+ of the polygon that contains it, using the file option. You can also
+ specify the exclude option, which reverses the operation of the filter
+ so that it only includes points that are NOT in the polygon.
+
+ For example, assume you have a polygon file that defines the border of
+ your county, called mycounty.txt. This command line will give you only
+ the points in your county:
+
+ gpsbabel -i geo -f 1.loc -x polygon,file=mycounty.txt \
+ -o mapsend -F 2.wpt
COMMON USAGE
extern filter_vecs_t radius_vecs;
extern filter_vecs_t duplicate_vecs;
extern filter_vecs_t arcdist_vecs;
+extern filter_vecs_t polygon_vecs;
static
fl_vecs_t filter_vec_list[] = {
"arc",
"Include Only Points Within Distance of Arc",
},
+ {
+ &polygon_vecs,
+ "polygon",
+ "Include Only Points Inside Polygon",
+ },
{
NULL,
NULL,
--- /dev/null
+/*
+ Inside/Outside polygon filter
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#include <stdio.h>
+#include <math.h>
+#include "defs.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+#define MYNAME "Polygon filter"
+
+extern queue waypt_head;
+
+static double pos_dist;
+static char *polyfileopt = NULL;
+static char *exclopt = NULL;
+
+#define OUTSIDE 0
+#define INSIDE 1
+#define LIMBO 2
+#define LIMBO_UP 4
+#define LIMBO_BEGIN 8
+#define BEGIN_UP 16
+#define BEGIN_HOR 32
+#define UP 64
+
+typedef struct {
+ unsigned short state;
+} extra_data;
+
+static
+arglist_t polygon_args[] = {
+ {"file", &polyfileopt, "File containing vertices of polygon"},
+ {"exclude", &exclopt, "Exclude points inside the polygon"},
+ {0, 0, 0}
+};
+
+static void polytest ( double lat1, double lon1,
+ double lat2, double lon2,
+ double lat3, double lon3,
+ unsigned short *state, int first, int last ) {
+
+ if ( lat1 == lat3 ) {
+ if ( lat2 < lat3 ) {
+ /* going down */
+ if (*state & LIMBO) {
+ if ( *state & LIMBO_UP ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO &~LIMBO_UP;
+ }
+ else if (*state & LIMBO_BEGIN) {
+ if ( *state & BEGIN_HOR ) {
+ *state = *state & ~BEGIN_HOR;
+ }
+ else if ( last ) {
+ if ( *state & BEGIN_UP ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP;
+ }
+ }
+ else if ( first && (lon1 > lon3)) {
+ *state |= LIMBO_BEGIN;
+ }
+ }
+ else if ( lat2 == lat3 ) {
+ if ( first & (lon1 > lon3 || lon2 > lon3)) {
+ *state |= LIMBO_BEGIN | BEGIN_HOR;
+ }
+ else if (last && (*state & LIMBO_BEGIN) && (*state & LIMBO)) {
+ if ( (!!(*state & LIMBO_UP)) != (!!(*state & BEGIN_UP))) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO & ~LIMBO_UP &
+ ~LIMBO_BEGIN & ~BEGIN_UP;
+ }
+ else if ( *state & LIMBO ) {
+ /* do nothing */
+ }
+ else {
+ if ( lon1 <= lon3 && lon2 > lon3 ) {
+ if ( *state & UP ) {
+ *state = *state | LIMBO_UP & ~UP;
+ }
+ *state = *state | LIMBO;
+ }
+ }
+ }
+ else {
+ /* going up */
+ if (*state & LIMBO) {
+ if ( !(*state & LIMBO_UP) ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO & ~LIMBO_UP;
+ }
+ else if (*state & LIMBO_BEGIN) {
+ if ( *state & BEGIN_HOR ) {
+ *state = *state & ~BEGIN_HOR | BEGIN_UP;
+ }
+ else if ( last ) {
+ if ( !(*state & BEGIN_UP) ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP;
+ }
+ }
+ else if ( first && (lon1 > lon3)) {
+ *state |= LIMBO_BEGIN | BEGIN_UP;
+ }
+ }
+ *state = *state & ~UP;
+ }
+ else if ( lat2 == lat3 ) {
+ if ( lat1 < lat3 ) {
+ if ( last ) {
+ if ( *state & BEGIN_UP ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP;
+ }
+ else if ( lon2 > lon3 ) {
+ *state |= LIMBO;
+ }
+ }
+ /* no case for lat1==lat3; that's above */
+ else {
+ if ( last ) {
+ if ( !(*state & BEGIN_UP) ) {
+ *state = *state ^ INSIDE;
+ }
+ *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP;
+ }
+ else if ( lon2 > lon3 ) {
+ *state |= LIMBO | LIMBO_UP;
+ }
+ else {
+ *state |= UP;
+ }
+ }
+ }
+ else {
+ if ( (lat1 > lat3 && lat2 < lat3) ||
+ (lat1 < lat3 && lat2 > lat3)) {
+ /* we only care if the lines might intersect */
+ if ( lon1 > lon3 && lon2 > lon3 ) {
+ *state = *state ^ INSIDE;
+ }
+ else if (!(lon1 <= lon3 && lon2 <= lon3)) {
+ /* we're inside the bbox of a diagonal line. math time. */
+ double loni = (lon2-lon1)/(lat2-lat1)*(lat3-lat1);
+ if ( loni > lon3 ) {
+ *state = *state ^ INSIDE;
+ }
+ }
+ }
+ }
+
+}
+
+#define BADVAL 999999
+
+void
+polygon_process(void)
+{
+ queue * elem, * tmp;
+ waypoint * waypointp;
+ waypoint ** comp;
+ int i, wc;
+ queue temp_head;
+ extra_data *ed;
+ double lat1, lon1, lat2, lon2;
+ double olat, olon;
+ int fileline = 0;
+ int first = 1;
+ int last = 0;
+
+ FILE *polyfile = fopen( polyfileopt, "r" );
+ if ( polyfile == NULL ) {
+ fatal(MYNAME ":Can't open %s for reading.\n",polyfileopt);
+ }
+
+ olat = olon = lat1 = lon1 = lat2 = lon2 = BADVAL;
+ while ( !feof(polyfile)) {
+ char line[200];
+ char *pound = NULL;
+ int argsfound = 0;
+
+ fgets( line, sizeof(line), polyfile );
+
+ fileline++;
+
+ pound = strchr( line, '#' );
+ if ( pound ) *pound = '\0';
+
+ lat2 = lon2 = BADVAL;
+ argsfound = sscanf( line, "%lf %lf", &lat2, &lon2 );
+
+ if ( argsfound != 2 && strspn(line, " \t\n") < strlen(line)) {
+ fprintf( stderr, "%s: Warning: Polygon file contains unusable vertex on line %d.\n", MYNAME, fileline );
+ }
+ else if ( lat1 != BADVAL && lon1 != BADVAL &&
+ lat2 != BADVAL && lon2 != BADVAL ) {
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+
+ waypointp = (waypoint *)elem;
+ if ( waypointp->extra_data ) {
+ ed = waypointp->extra_data;
+ }
+ else {
+ ed = xcalloc(1, sizeof(*ed));
+ ed->state = OUTSIDE;
+ waypointp->extra_data = ed;
+ }
+ if ( olat != BADVAL && olon != BADVAL &&
+ olat == lat2 && olon == lon2 ) {
+ last = 1;
+ }
+ polytest( lat1, lon1, lat2, lon2,
+ waypointp->position.latitude.degrees,
+ waypointp->position.longitude.degrees,
+ &ed->state, first, last );
+ first = 0;
+ last = 0;
+ }
+ }
+ if ( olat != BADVAL && olon != BADVAL &&
+ olat == lat2 && olon == lon2 ) {
+ olat = BADVAL;
+ olon = BADVAL;
+ lat1 = BADVAL;
+ lon1 = BADVAL;
+ first = 1;
+ }
+ else if ( lat1 == BADVAL || lon1 == BADVAL ) {
+ olat = lat2;
+ olon = lon2;
+ lat1 = lat2;
+ lon1 = lon2;
+ }
+ else {
+ lat1 = lat2;
+ lon1 = lon2;
+ }
+ }
+
+ fclose(polyfile);
+
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ waypoint *wp = (waypoint *) elem;
+ ed = wp->extra_data;
+ wp->extra_data = NULL;
+ if ( ed ) {
+ if (((ed->state & INSIDE) == OUTSIDE ) == (exclopt == NULL)) {
+ waypt_del(wp);
+ waypt_free(wp);
+ continue;
+ }
+ xfree( ed );
+ }
+ }
+}
+
+void
+polygon_init(const char *args) {
+ /* do nothing */
+}
+
+void
+polygon_deinit(void) {
+ /* do nothing */
+}
+
+filter_vecs_t polygon_vecs = {
+ polygon_init,
+ polygon_process,
+ polygon_deinit,
+ polygon_args
+};
--- /dev/null
+41.270000 -84.847384
+41.271057 -84.806490
+41.271079 -84.803581
+41.271079 -84.803581
+41.270942 -84.803580
+41.252531 -84.803492
+41.252531 -84.803492
+41.184959 -84.803475
+41.173889 -84.803472
+41.173203 -84.803594
+41.164649 -84.803413
+41.164169 -84.803420
+41.161573 -84.803460
+41.154117 -84.803573
+41.140520 -84.803780
+41.130773 -84.803501
+41.121414 -84.803234
+41.096783 -84.803341
+41.096783 -84.803341
+41.089302 -84.803374
+41.077432 -84.803367
+41.009551 -84.803325
+40.989209 -84.803313
+40.989209 -84.803313
+40.922377 -84.802935
+40.922377 -84.802935
+40.920577 -84.880807
+40.920577 -84.880807
+40.920311 -84.899804
+40.920311 -84.899804
+40.920237 -84.906200
+40.920237 -84.906200
+40.919632 -84.939126
+40.919632 -84.939638
+40.918588 -84.997291
+40.918588 -84.997291
+40.918447 -85.015168
+40.918447 -85.016068
+40.918447 -85.017668
+40.918047 -85.049068
+40.918047 -85.053468
+40.917847 -85.064268
+40.917847 -85.073868
+40.917847 -85.073868
+40.917447 -85.109669
+40.917447 -85.109669
+40.917247 -85.133662
+40.917247 -85.138269
+40.916547 -85.167070
+40.916947 -85.223371
+40.917047 -85.261571
+40.917047 -85.261571
+40.917047 -85.267360
+40.917047 -85.267360
+40.917032 -85.270180
+40.917023 -85.271123
+40.917011 -85.272372
+40.917011 -85.272372
+40.916994 -85.274150
+40.916994 -85.274150
+40.916947 -85.284172
+40.916947 -85.285948
+40.916947 -85.287972
+40.916947 -85.289672
+40.916947 -85.290204
+40.916947 -85.290204
+40.917046 -85.324973
+40.916946 -85.325373
+40.917046 -85.335973
+40.917046 -85.335973
+40.931446 -85.335873
+40.934746 -85.335973
+40.945846 -85.335573
+40.946246 -85.335673
+40.960346 -85.335673
+40.966746 -85.335573
+40.966746 -85.335573
+40.973192 -85.335418
+40.973192 -85.335418
+41.002047 -85.335374
+41.005347 -85.335274
+41.005347 -85.335274
+41.019947 -85.335574
+41.019947 -85.335574
+41.023138 -85.335574
+41.023138 -85.335574
+41.028400 -85.335626
+41.028400 -85.335626
+41.028680 -85.335631
+41.028680 -85.335631
+41.034047 -85.335774
+41.036347 -85.336074
+41.036347 -85.336074
+41.043516 -85.336249
+41.043516 -85.336249
+41.044447 -85.336274
+41.059047 -85.336574
+41.074947 -85.336974
+41.074947 -85.336974
+41.078620 -85.336974
+41.078620 -85.336974
+41.081370 -85.337035
+41.081370 -85.337035
+41.082627 -85.337075
+41.084247 -85.337075
+41.084247 -85.337075
+41.089647 -85.337275
+41.133759 -85.337800
+41.143299 -85.337827
+41.143299 -85.337827
+41.145540 -85.337834
+41.145540 -85.337834
+41.151009 -85.338178
+41.172790 -85.338402
+41.179120 -85.338552
+41.179260 -85.309842
+41.205086 -85.309537
+41.208912 -85.309716
+41.208912 -85.309716
+41.209609 -85.309724
+41.209609 -85.309724
+41.218262 -85.309657
+41.218720 -85.309808
+41.228211 -85.309910
+41.229675 -85.309950
+41.229675 -85.309950
+41.233139 -85.309660
+41.233139 -85.309660
+41.235062 -85.309506
+41.235192 -85.309502
+41.246997 -85.309775
+41.250047 -85.309586
+41.251009 -85.309143
+41.264071 -85.307748
+41.264071 -85.307748
+41.263809 -85.262791
+41.263851 -85.255698
+41.263851 -85.255698
+41.263850 -85.255648
+41.263850 -85.255648
+41.263805 -85.249531
+41.264283 -85.192097
+41.264283 -85.192097
+41.264449 -85.182307
+41.264449 -85.182307
+41.264820 -85.154950
+41.264820 -85.154950
+41.264961 -85.144213
+41.264961 -85.144213
+41.265046 -85.137394
+41.265046 -85.137394
+41.265091 -85.135030
+41.265829 -85.086692
+41.265562 -85.077749
+41.265562 -85.077749
+41.265756 -85.065254
+41.265756 -85.065254
+41.265822 -85.061017
+41.265822 -85.061017
+41.265860 -85.058621
+41.266469 -85.020092
+41.266557 -85.016245
+41.266557 -85.016245
+41.266740 -85.008277
+41.266740 -85.008277
+41.267781 -84.962627
+41.268149 -84.941620
+41.268218 -84.938770
+41.268218 -84.938164
+41.268368 -84.926845
+41.268627 -84.914822
+41.268963 -84.901055
+41.268963 -84.901055
+41.268974 -84.900612
+41.268974 -84.900612
+41.269170 -84.892632
+41.270000 -84.847384
--- /dev/null
+BEGIN SYMBOL
+41.14703, -85.11092, N.E.R.D. by Enos Shenk Unknown Cache (3/3)
+41.13940, -85.10142, Fallen Timbers by TeamMJ Traditional Cache (2/2)
+41.14415, -85.14415, Historic Iron Bridges by Genoist (1/2 of TeamSJ1) Locationless (Reverse) Cache (1/1)
+41.12890, -85.11163, Mastadon Trek 2 by Genoist and Dogvetusa Traditional Cache (2/2)
+41.16413, -85.14688, NYC Trail by VistaAL Traditional Cache (1/1.5)
+41.15900, -85.15418, Craftily Concealed Containers by Warm Fuzzies Multi-Cache (4/2)
+41.12210, -85.11097, Land of Lost Auto Parts by Genoist and The Zymurgist Traditional Cache (1/5)
+41.17732, -85.15117, The Farm by AParks1569 Traditional Cache (1.5/1.5)
+41.10757, -85.13087, Swonderful by Genoist and The Zymurgist Traditional Cache (2/5)
+41.12733, -85.06728, Dr. Mengerson I Preserve by Genoist Traditional Cache (2/2)
+41.10417, -85.15167, Clue by Warm Fuzzies Multi-Cache (3.5/2)
+41.10823, -85.16212, Son of Pez by Enos Shenk Traditional Cache (1.5/1.5)
+41.09278, -85.14073, Urbana #3: Dodgy Deals by Enos Shenk Traditional Cache (2.5/1.5)
+41.09258, -85.09258, Secret Squirrels by Enos Shenk & Panic! Unknown Cache (4/1)
+41.08748, -85.13762, A King's Ransom by Team ABC and The GeoStars Team Traditional Cache (1.5/1)
+41.08427, -85.13597, Urbana #4: The City She Loves Me by Enos Shenk & Athena Traditional Cache (3.5/2)
+41.08582, -85.07230, Caribbean Cache by Genoist and Dogvetusa Traditional Cache (3/2)
+41.08190, -85.17180, Earthling Vector Luna- 2nd Phase by Earthling and Heavenbound Traditional Cache (1/1.5)
+41.08400, -85.05387, Earthling Vector Sol by Earthling & Heavenbound Traditional Cache (1.5/1.5)
+41.20673, -85.03985, The Sarsaparilla Cache by Cashconnect Traditional Cache (2/1.5)
+41.06353, -85.13400, Sky High by Enos Shenk Virtual Cache (1/3)
+41.09880, -85.21725, We Support Our Troops by Genoist and The Zymurgist Traditional Cache (2/2.5)
+41.06950, -85.19750, Shortwave by Warm Fuzzies Unknown Cache (4/2.5)
+41.06255, -85.04757, Starfall by Enos Shenk Traditional Cache (2/2.5)
+41.07482, -85.01957, Fly Like an Eagle by Team SJ1 Traditional Cache (2/2)
+41.04714, -85.16617, Perfectly Perplexing Puzzles by Warm Fuzzies Multi-Cache (5/3.5)
+41.07197, -85.01863, Arrow Haven (2/4) by Genoist Traditional Cache (2/2.5)
+41.07183, -85.01850, Heat Death (3/4) by Genoist Traditional Cache (2/3)
+41.06827, -85.01655, Abbadon by Genoist Traditional Cache (1.5/4)
+41.01503, -85.13290, Earthling Vector Pluto by Earthling & Heavenbound Traditional Cache (1/1.5)
+41.26535, -84.98950, Outstanding In Its Field Cache by kwbach Traditional Cache (2/2)
+41.00470, -85.05742, Earthling Vector Perelandra by Earthling & Heavenbound Multi-Cache (4/1.5)
+41.04247, -85.27570, KWAANTINAKAANI by Northmill Jo-Jo Beans and E-Bone Letterbox Hybrid (2/1)
+41.01760, -85.25190, Earthling Vector Terra by Earthling & Heavenbound Traditional Cache (1.5/2.5)
+40.97610, -85.22277, 47520 Feet by kidCraZy Traditional Cache (1/1.5)
+END
-o xmap -F ${TMPDIR}/arcdist.txt
compare ${TMPDIR}/arcdist.txt reference/arcdist_output.txt
+#
+# Polygon filter
+#
+rm -f ${TMPDIR}/polygon.txt
+${PNAME} -i xmap -f reference/arcdist_input.txt \
+ -x polygon,file=reference/polygon_allencty.txt \
+ -o xmap -F ${TMPDIR}/polygon.txt
+compare ${TMPDIR}/polygon.txt reference/polygon_output.txt
+